Skip to content

MA0008: Use proper blittable type check instead of IsReferenceType#1062

Merged
meziantou merged 1 commit into
mainfrom
fix/ma0008-complete-blittable-type-check
Mar 26, 2026
Merged

MA0008: Use proper blittable type check instead of IsReferenceType#1062
meziantou merged 1 commit into
mainfrom
fix/ma0008-complete-blittable-type-check

Conversation

@meziantou
Copy link
Copy Markdown
Owner

Problem

The MA0008 (UseStructLayoutAttributeAnalyzer) rule is documented to only fire when all struct fields are blittable, but the implementation only checked member.Type.IsReferenceType. This meant it would incorrectly flag structs with non-blittable value-type fields like bool, char, and decimal.

Changes

New IsBlittableType() extension method

Added to TypeSymbolExtensions.cs, checking the complete set of blittable types per the .NET specification:

  • Primitive blittable types: byte, sbyte, short, ushort, int, uint, long, ulong, float, double, IntPtr, UIntPtr
  • Pointer types
  • Enums (backed by blittable integer types)
  • User-defined structs whose instance fields are all recursively blittable

Non-blittable value types (bool, char, decimal, DateTime, etc.) correctly return false.

Updated analyzer

Replaced the member.Type.IsReferenceType check in UseStructLayoutAttributeAnalyzer with !member.Type.IsBlittableType().

New tests (11 added)

  • bool, char, decimal fields → no diagnostic (non-blittable)
  • nint/nuint (IntPtr/UIntPtr), float/double fields → diagnostic (blittable)
  • Enum fields → diagnostic (blittable)
  • Blittable nested struct → diagnostic
  • Non-blittable nested struct → no diagnostic
  • Mixed blittable + non-blittable → no diagnostic

All 18 tests pass on both default Roslyn and Roslyn 4.2.

The analyzer previously only checked IsReferenceType, which incorrectly
flagged structs with non-blittable value-type fields (bool, char, decimal).

Add IsBlittableType() extension that checks the complete set of blittable
types: byte, sbyte, short, ushort, int, uint, long, ulong, float, double,
IntPtr, UIntPtr, pointers, enums, and structs with only blittable fields.
@meziantou meziantou merged commit 96adf3c into main Mar 26, 2026
13 checks passed
@meziantou meziantou deleted the fix/ma0008-complete-blittable-type-check branch March 26, 2026 18:43
IhateTrains added a commit to ParadoxGameConverters/ImperatorToCK3 that referenced this pull request Mar 27, 2026
Updated
[Meziantou.Analyzer](https://github.com/meziantou/Meziantou.Analyzer)
from 3.0.26 to 3.0.28.

<details>
<summary>Release notes</summary>

_Sourced from [Meziantou.Analyzer's
releases](https://github.com/meziantou/Meziantou.Analyzer/releases)._

## 3.0.28

NuGet package:
<https://www.nuget.org/packages/Meziantou.Analyzer/3.0.28>

## What's Changed
* MA0008: Use proper blittable type check instead of IsReferenceType by
@​meziantou in meziantou/Meziantou.Analyzer#1062


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.27...3.0.28

## 3.0.27

NuGet package:
<https://www.nuget.org/packages/Meziantou.Analyzer/3.0.27>

## What's Changed
* MA0190: Suggest converting [GeneratedRegex] partial methods to partial
properties (C# 13+) by @​Copilot in
meziantou/Meziantou.Analyzer#1060


**Full Changelog**:
meziantou/Meziantou.Analyzer@3.0.26...3.0.27

Commits viewable in [compare
view](meziantou/Meziantou.Analyzer@3.0.26...3.0.28).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Meziantou.Analyzer&package-manager=nuget&previous-version=3.0.26&new-version=3.0.28)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
This was referenced May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant